home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / pcl4c35.zip / TERM.C < prev    next >
Text File  |  1993-05-16  |  13KB  |  436 lines

  1. /*
  2. **                    --- term.c ---
  3. **
  4. **  EXAMPLE CODE: Terminal emulator. Can transfer files using
  5. **  ASCII, XMODEM, YMODEM, and YMODEM-G protocols.
  6. **
  7. **  See TERM.H for configuration parameters.
  8. **
  9. **  Link with TERM_IO, MODEM_IO, DIR_IO, CRC, DOS, AMODEM, XYMODEM,
  10. **  and XYPACKET. See TERM makefiles.
  11. **
  12. **  Do NOT select YMODEM-G when using a null modem cable unless you are
  13. **  certain that RTS & CTS are reversed ( this is usually not true ).
  14. **
  15. **  This example program (not the PCL4C library) is donated to
  16. **  the Public Domain by MarshallSoft Computing, Inc. It is
  17. **  provided as an example of the use of the PCL4C.
  18. **
  19. */
  20.  
  21. #include <stdio.h>
  22. #include <fcntl.h>
  23. #include <sys\types.h>
  24. #include <sys\stat.h>
  25. #include "pcl4c.h"
  26. #include "ascii.h"
  27. #include "term.h"
  28. #include "dir_io.h"
  29.  
  30. #define FALSE 0
  31. #define TRUE !FALSE
  32. #define NORMAL 0x07
  33. #define INVERSE 0x70
  34. #define MESSAGE_POS 48
  35.  
  36. void MyCrtWrite();
  37. void MyStart();
  38. void ProcessESC();
  39. void ShowProtocol();
  40. void ShowMessage();
  41. void MyExit();
  42. void SayFilename();
  43. void ErrorCheck();
  44.  
  45. int RxAscii(int,char[],char[],int,int,int,int,int,int);
  46. int TxAscii(int,char[],char[],int,int,int,int,int);
  47.  
  48. int RxyModem(int,char[],char[],int,int);
  49. int TxyModem(int,char[],char[],int,int);
  50.  
  51. /*** Global variables ***/
  52.  
  53. #define SIO_BUFFER_SIZE 2048
  54. int Port;               /* current COM port [0..3] */
  55. char FileSpec[15];      /* file name specification */
  56. char Filename[15];      /* file name buffer */
  57. char Buffer[1024];      /* block buffer */
  58. char RxBuf[SIO_BUFFER_SIZE];  /* receive buffer */
  59. char *BaudRate[10] =  {"300","600","1200","2400","4800","9600",
  60.                        "19200","38400","57600","115200"};
  61. int BaudCode;           /* baud rate code ( index into BaudRate[] ) */
  62. char *ModelText[4] = {"Small","Compact","Medium","Large"};
  63. char NCGchar   = NAK;
  64. int  OneKflag  = FALSE;
  65. int  BatchFlag = FALSE;
  66. char Protocol  = 'X';
  67. char TermChar  = 0x00;
  68. int  CharPace  = 0;
  69. int  Timeout   = 10;
  70. int  EchoFlag  = TRUE;
  71.  
  72. /*** main program ***/
  73.  
  74. main(argc,argv)
  75. int argc;
  76. char *argv[];
  77. {int DataFlag = FALSE;
  78.  char c;
  79.  int i, k;
  80.  int n, rc;
  81.  int Delta;         /* delta port status */
  82.  int Status;        /* port status */
  83.  char Version;
  84.  char temp[81];
  85.  /* right number of parameters ? */
  86.  if(argc!=3)
  87.      {printf("Usage: 'TERM port baud' -- example 'TERM 1 9600'\n");
  88.       exit(1);
  89.      }
  90.  /* get port number from command line */
  91.  Port = atoi(argv[1]) - 1;
  92.  if((Port<0) || (Port>11))
  93.      {printf("Port must be 1 to 12\n");
  94.       exit(1);
  95.      }
  96.  /* get baud rate from command line */
  97.  BaudCode = BaudMatch(argv[2]);
  98.  if(BaudCode<0)
  99.      {printf("Cannot recognize baud rate = %s\n",argv[2]);
  100.       exit(1);
  101.      }
  102. #if 0
  103.  /*** Custom Configuration ***/
  104.  SioIRQ(COM1,IRQ4,FirstISR);
  105.  SioIRQ(COM2,IRQ3,SecondISR);
  106.  /* use IRQ2 for COM3 */
  107.  SioIRQ(COM3,IRQ2,ThirdISR);
  108.  /* use IRQ5 for COM4 */
  109.  SioIRQ(COM4,IRQ5,FourthISR);
  110. #endif
  111.  /* setup receive buffer */
  112.  ErrorCheck( SioRxBuf(Port,RxBuf,Size2K) );
  113.  /* set parms & reset (initialize) COM port */
  114.  ErrorCheck( SioParms(Port,NoParity,OneStopBit,WordLength8) );
  115.  MyStart(Port,BaudCode);
  116.  /* set DTR and RTS */
  117.  SioDTR(Port,'S');
  118.  SioRTS(Port,'S');
  119.  /* init CRC table */
  120.  InitCRC();
  121.  /* initialize screen */
  122.  Scroll(0,0,24,79,0,NORMAL);
  123.  /* display status message */
  124.  sprintf(temp," COM%d %s %c 'ESC for menu'  ",1+Port,BaudRate[BaudCode],Protocol);
  125.  ShowMessage(0,temp);
  126.  Position(1,0);
  127.  /* display some info */
  128.  puts("TERM 5/1/93");
  129.  Version = SioInfo('V');
  130.  printf("Library = %d.%d\n",Version/16,Version%16);
  131.  printf("Memory Model = %s\n",ModelText[3&SioInfo('M')] );
  132. #if RTS_CTS_CONTROL
  133.  SioFlow(Port,7*ONE_SECOND);
  134.  printf("Flow Control enabled. CTS = ");
  135.  if(SioCTS(Port)) puts("ON");
  136.  else puts("OFF");
  137. #endif
  138.  /* Set FIFO level */
  139.  if( SioFIFO(Port,LEVEL_14) ) puts("INS16550 detected");
  140.  /* clear PCL4C receive buffer */
  141.  ErrorCheck( SioRxFlush(Port) );
  142.  
  143.  /* see TERM.H for definition of AT_COMMAND_SET */
  144. #if AT_COMMAND_SET
  145.  /* wait for Modem to say its ready */
  146.  printf("Waiting for Modem DSR.");
  147.  while( !SioDSR(Port) )
  148.      {
  149.       if(SioKeyPress()||SioBrkKey()) MyExit(0,"Aborted by user");
  150.       putchar('.');
  151.       SioDelay(18);
  152.      }
  153.  putchar('\n');
  154.  /* initialize (Hayes compatible) modem */
  155.  SendTo(Port,"!AT!!~");
  156.  SendTo(Port,"!AT E1 S7=60 S11=60 V1 X1 Q0 S0=1!");
  157.  if(WaitFor(Port,"OK")) printf("\nMODEM READY\n");
  158.  else printf("\nWARNING: Expected OK not received\n");
  159. #endif
  160.  
  161.  /* enter terminal loop */
  162.  SioRxFlush(Port);
  163.  while(1)
  164.      {/* Control-BREAK ? */
  165.       if(SioBrkKey()) MyExit(0,"User pressed Ctrl-BREAK");
  166.       /* was key pressed ? */
  167.       if(SioKeyPress())
  168.           {/* read key press */
  169.            i = SioKeyRead();
  170.            if((char)i==ESC)
  171.                {/* process user's request */
  172.                 ProcessESC();
  173.                 ShowMessage(strlen(BaudRate[BaudCode])+9,"'ESC for Menu' ");
  174.                 continue;
  175.                }
  176.            else PutChar(Port,i);
  177.           }
  178.       /* was break detected ? */
  179.       if( SioBrkSig(Port,'D') ) DisplayLine("BREAK detected ",NULL,0);
  180.       /* any incoming over serial port ? */
  181.       i = GetChar(Port,0);
  182.       if(i>-1)
  183.           {/* good character */
  184.            if(DataFlag&((i<0x20)||(i>0x7e)))
  185.                {MyCrtWrite('^');
  186.                 MyCrtWrite('@'+i);
  187.                }
  188.            else MyCrtWrite(i);
  189.           }
  190.       /* any change in DCD or DSR ? */
  191.       Delta = SioModem(Port,DeltaDCD|DeltaDSR);
  192.       if(Delta)
  193.           {/* display new status */
  194.            Status = SioModem(Port,(char)(DCD|DSR));
  195.            if(!Status&DeltaDCD) MyExit(0,"Dropped DSD");
  196.            if(!Status&DeltaDSR) MyExit(0,"Dropped DSR");
  197.           }
  198.      } /* end -- key pressed */
  199. }
  200.  
  201. /*** write to screen except for bottom line ***/
  202.  
  203. void MyCrtWrite(ch)
  204. char ch;
  205. {/* write character */
  206.  SioCrtWrite(ch);
  207.  /* scroll all but bottom line */
  208.  if(GetRow()==24)
  209.     {Scroll(0,0,23,79,1,NORMAL);
  210.      Position(23,0);
  211.     }
  212. }
  213.  
  214. /*** make multiple attempts to reset port ***/
  215.  
  216. void MyStart(Port,BaudCode)
  217. int Port;
  218. int BaudCode;
  219. {int i, rc;
  220.  /* try up to 3 times to reset COM port */
  221.  for(i=0;i<3;i++)
  222.      {printf("Resetting COM%d at %s baud\n",Port+1,BaudRate[BaudCode]);
  223.       if( (rc = SioReset(Port,BaudCode))==0) return;
  224.       if(rc<0) MyExit(rc,"Error resetting port");
  225.       SioDone(Port);
  226.       /* display errors */
  227.       if(rc&OverrunError) puts("Overrun Error");
  228.       if(rc&ParityError)  puts("Parity Error");
  229.       if(rc&FramingError) puts("Framing Error");
  230.       if(rc&BreakDetect)  puts("Break Detect");
  231.      }
  232.  exit(1);
  233. }
  234.  
  235. /*** find baud rate string in table ***/
  236.  
  237. int BaudMatch(ptr)
  238. char *ptr;
  239. {int i;
  240.  /* find baud rate in table */
  241.  for(i=0;i<10;i++) if(strcmp(BaudRate[i],ptr)==0) return(i);
  242.  return(-1);
  243. }
  244.  
  245. /*** user pressed Escape */
  246.  
  247. void ProcessESC()
  248. {int i;
  249.  int rc;
  250.  int c1, c2;
  251.  char Answer[2]; /* array for 1 char answer */
  252.  int row, col;
  253.  /* user pressed <ESC> */
  254.  Answer[0] = '?';
  255.  Answer[1] = '\0';
  256.  DisplayLine("Q)uit P)rotocol S)end R)eceive: ",Answer,1);
  257.  if(strlen(Answer)) switch(toupper(Answer[0]))
  258.      {
  259.       case 'P':
  260. #if RTS_CTS_CONTROL
  261.           DisplayLine("A)scii X)modem Y)modem ymodem-G): ",Answer,1);
  262. #else
  263.           DisplayLine("A)scii X)modem Y)modem: ",Answer,1);
  264. #endif
  265.           if(strlen(Answer)) switch( toupper(Answer[0]) )
  266.                {
  267.                 case 'A':
  268.                     Protocol = 'A';
  269.                     ShowProtocol();
  270.                     TermChar = 0x18;  /* CAN or control-X */
  271.                     CharPace = 0;     /* no inter-byte delay */
  272.                     Timeout = 7;      /* timeout after 7 seconds */
  273.                     EchoFlag = TRUE;  /* do local echo */
  274.                     DisplayLine("Protocol = ASCII",NULL,1);
  275.                     break;
  276.                 case 'X':
  277.                     Protocol = 'X';
  278.                     ShowProtocol();
  279.                     OneKflag = FALSE;
  280.                     BatchFlag = FALSE;
  281.                     NCGchar = NAK;
  282.                     DisplayLine("Protocol = XMODEM",NULL,1);
  283.                     break;
  284.                 case 'Y':
  285.                     Protocol = 'Y';
  286.                     ShowProtocol();
  287.                     OneKflag = TRUE;
  288.                     BatchFlag = TRUE;
  289.                     NCGchar = 'C';
  290.                     DisplayLine("Protocol = YMODEM",NULL,1);
  291.                     break;
  292. #if RTS_CTS_CONTROL
  293.                 case 'G':
  294.                     Protocol = 'G';
  295.                     ShowProtocol();
  296.                     OneKflag = TRUE;
  297.                     BatchFlag = TRUE;
  298.                     NCGchar = 'G';
  299.                     DisplayLine("Protocol = YMODEM-G",NULL,1);
  300.                     break;
  301. #endif
  302.                 default:
  303.                     DisplayLine("Must answer X, Y, or G",NULL,1);
  304.                     break;
  305.                }
  306.           break;
  307.       case 'Q':
  308.           MyExit(0,"User pressed ESC");
  309.           break;
  310.       case 'R':
  311.           ShowMessage(strlen(BaudRate[BaudCode])+9,"'CTRL-X aborts'");
  312.           if(Protocol=='A')
  313.               {/* Ascii */
  314.                DisplayLine("Enter filename:",Filename,15);
  315.                if(strlen(Filename)==0) break;
  316.                RxAscii(Port,Filename,Buffer,1024,SIO_BUFFER_SIZE,FALSE,TermChar,Timeout,EchoFlag);
  317.                break;
  318.               }
  319.           /* XMODEM / YMODEM receive */
  320.           if(BatchFlag)
  321.                {do
  322.                     {/* receive files till get empty filename */
  323.                      RxyModem(Port,Filename,Buffer,NCGchar,BatchFlag);
  324.                      if(SioKeyPress()) break;
  325.                     } while(Filename[0]!='\0');
  326.                }
  327.           else /* not Batch */
  328.                {DisplayLine("Enter filename:",Filename,15);
  329.                 if(strlen(Filename)==0) break;
  330.                 RxyModem(Port,Filename,Buffer,NCGchar,BatchFlag);
  331.                }
  332.           break;
  333.       case 'S':
  334.           ShowMessage(strlen(BaudRate[BaudCode])+9,"'CTRL-X aborts'");
  335.           DisplayLine("Enter filename:",FileSpec,15);
  336.           if(strlen(FileSpec)==0) break;
  337.           if(Protocol=='A')
  338.               {/* Ascii */
  339.                TxAscii(Port,FileSpec,Buffer,1024,FALSE,CharPace,TermChar,EchoFlag);
  340.                break;
  341.               }
  342.           if(BatchFlag)
  343.                {/* YMODEM send */
  344.                 if(FindFirst(FileSpec,Filename))
  345.                   {SayFilename(Filename);
  346.                    TxyModem(Port,Filename,Buffer,OneKflag,BatchFlag);
  347.                    while(FindNext(Filename))
  348.                      {SioDelay(4);
  349.                       SayFilename(Filename);
  350.                       TxyModem(Port,Filename,Buffer,OneKflag,BatchFlag);
  351.                      }
  352.                    /* send empty filename */
  353.                    Filename[0] = '\0';
  354.                    SioDelay(5);
  355.                    TxyModem(Port,Filename,Buffer,OneKflag,BatchFlag);
  356.                   }
  357.                }
  358.           else
  359.                {/* XMODEM send */
  360.                 TxyModem(Port,FileSpec,Buffer,OneKflag,BatchFlag);
  361.                }
  362.           break;
  363.      default:
  364.           DisplayLine("Must answer Q, P, S, or R",NULL,0);
  365.           break;
  366.     } /* end switch */
  367. }
  368.  
  369. /*** show protocol choosen ***/
  370.  
  371. void ShowProtocol()
  372. {int SaveRow;
  373.  int SaveCol;
  374.  SaveRow = GetRow();
  375.  SaveCol = GetCol();
  376.  Position(24,MESSAGE_POS+strlen(BaudRate[BaudCode])+7);
  377.  AttrWrite(Protocol,INVERSE);
  378.  Position(SaveRow,SaveCol);
  379. }
  380.  
  381. /*** show chosen message ***/
  382.  
  383. void ShowMessage(Pos,Msg)
  384. int Pos;
  385. char *Msg;
  386. {int i;
  387.  int SaveRow;
  388.  int SaveCol;
  389.  int Col;
  390.  SaveRow = GetRow();
  391.  SaveCol = GetCol();
  392.  Col = MESSAGE_POS+Pos;
  393.  for(i=0;i<strlen(Msg);i++)
  394.    {Position(24,Col++);
  395.     AttrWrite(Msg[i],INVERSE);
  396.    }
  397.  Position(SaveRow,SaveCol);
  398. }
  399.  
  400. /*** exit program ***/
  401.  
  402. void MyExit(code,msg)
  403. int code;
  404. char *msg;
  405. {int rc;
  406.  if(code<0) SioError(code);
  407.  /* Assert UART break & sign off */
  408.  SioBrkSig(Port,'A');
  409.  printf("\nTERMINATING: %s\n",msg);
  410.  SioDelay(ONE_SECOND/2);
  411.  SioDone(Port);
  412.  exit(0);
  413. }
  414.  
  415. /*** display file name in status area ***/
  416.  
  417. void SayFilename(Text)
  418. char *Text;
  419. {char Temp[40];
  420.  strcpy(Temp,"Sending ");
  421.  strcat(Temp,Text);
  422.  DisplayLine(Temp,NULL,0);
  423.  SioDelay(ONE_SECOND/2);
  424. }
  425.  
  426. /*** check for error ***/
  427.  
  428. void ErrorCheck(Code)
  429. int Code;
  430. {/* trap PCL error codes */
  431.  if(Code<0)
  432.      {SioError(Code);
  433.       SioDone(Port);
  434.       exit(1);
  435.      }
  436. } /* end ErrorCheck */